package org.breathe.command.impl.zset;

import org.breathe.command.Command;
import org.breathe.command.CommandType;
import org.breathe.datastruct.RedisBytes;
import org.breathe.datastruct.RedisData;
import org.breathe.datastruct.impl.RedisZSet;
import org.breathe.protocal.Resp;
import org.breathe.protocal.decode.BulkString;
import org.breathe.protocal.decode.Errors;
import org.breathe.protocal.decode.RespInteger;
import org.breathe.server.core.RedisCore;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: breathe
 * @createTime: 2025-05-16
 */
public class ZAdd implements Command {
    private final RedisCore redisCore;
    private RedisBytes key;
    private List<Double> scores;
    private List<RedisBytes> members;
    public ZAdd(RedisCore redisCore) {
        this.redisCore = redisCore;
    }
    @Override
    public CommandType getType() {
        return CommandType.ZADD;
    }

    @Override
    public void setContext(Resp[] array) {
        if (array.length < 4 || (array.length - 2) % 2 != 0) {
            throw new IllegalArgumentException("argument not enough");
        }
        key = ((BulkString)array[1]).getContent();
        scores = new ArrayList<>();
        members = new ArrayList<>();
        for (int i = 2; i < array.length; i += 2) {
            scores.add(Double.parseDouble(((BulkString)array[i]).getContent().getString()));
            members.add(((BulkString)array[i + 1]).getContent());
        }
    }

    @Override
    public Resp handle() {
        try {
            RedisData redisData = redisCore.get(key);
            RedisZSet redisZset = null;
            if (redisData == null) {
                redisZset = new RedisZSet();
                redisCore.put(key, redisZset);
            } else if (redisData instanceof RedisZSet zSet) {
                redisZset = zSet;
            }
            int count = 0;
            for (int i = 0; i < scores.size(); i ++) {
                assert redisZset != null;
                if (redisZset.add(scores.get(i), members.get(i))) {
                    count ++;
                }
            }
            return new RespInteger(count);
        } catch (Exception e) {
            return new Errors("command run fail");
        }
    }

    @Override
    public boolean writeCommand() {
        return true;
    }
}
